package com.xinqi.modules.discuss.notice.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xinqi.common.base.enums.YesNoNumberEnum;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.response.R;
import com.xinqi.common.core.enums.ClassRoleEnum;
import com.xinqi.common.core.enums.DiscussReleaseStatusEnum;
import com.xinqi.common.mybatis.data.service.impl.BaseServiceImpl;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.modules.course.clazz.client.ClassStudentClient;
import com.xinqi.modules.course.clazz.dto.rsp.ClassStudentResultDTO;
import com.xinqi.modules.discuss.notice.domain.CourseNoticeEntity;
import com.xinqi.modules.discuss.notice.domain.CourseNoticeStudentLogEntity;
import com.xinqi.modules.discuss.notice.dto.req.CourseNoticeStudentLogQueryDTO;
import com.xinqi.modules.discuss.notice.dto.rsp.CourseNoticeResultDTO;
import com.xinqi.modules.discuss.notice.dto.rsp.CourseNoticeStudentLogResultDTO;
import com.xinqi.modules.discuss.notice.mapper.CourseNoticeStudentLogMapper;
import com.xinqi.modules.discuss.notice.service.CourseNoticeStudentLogService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 服务层实现
 *
 * @author: yyzhen
 * @date: 2023/03/21
 */
@Service("courseNoticeStudentLogService")
@RequiredArgsConstructor
public class CourseNoticeStudentLogServiceImpl extends BaseServiceImpl<CourseNoticeStudentLogMapper, CourseNoticeStudentLogEntity> implements CourseNoticeStudentLogService {

    private final ClassStudentClient classStudentClient;

    /**
     * 根据公告删除
     *
     * @Title:
     * @MethodName: deleteByContentId
     * [contentId]
     * @Return void
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/21 15:55
     */
    @Override
    public void deleteByContentId(Long contentId) {
        this.baseMapper.delete(new LambdaQueryWrapper<CourseNoticeStudentLogEntity>()
            .eq(CourseNoticeStudentLogEntity::getContentId, contentId));
    }

    /**
     * 根据公告批量删除
     *
     * @Title:
     * @MethodName: deleteByContentIds
     * [contentIds]
     * @Return void
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/21 15:55
     */
    @Override
    public void deleteByContentIds(List<Long> contentIds) {
        this.baseMapper.delete(new LambdaQueryWrapper<CourseNoticeStudentLogEntity>()
            .in(CourseNoticeStudentLogEntity::getContentId, contentIds));
    }

    /**
     * 通过公告ID和学生ID获取详细
     *
     * @Title:
     * @MethodName: selectByNoticeIdAndStudentId
     * [contentId, studentId]
     * @Return com.xinqi.modules.discuss.notice.domain.CourseNoticeStudentLogEntity
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/21 15:56
     */
    @Override
    public CourseNoticeStudentLogEntity selectByNoticeIdAndStudentId(Long contentId, Long studentId) {
        LambdaUpdateWrapper<CourseNoticeStudentLogEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(CourseNoticeStudentLogEntity::getContentId, contentId)
            .eq(CourseNoticeStudentLogEntity::getStudentId, studentId)
            .last("limit 1");
        return this.baseMapper.selectOne(wrapper);
    }

    /**
     * 通过公告ID获取列表
     *
     * @Title:
     * @MethodName: selectByContentId
     * [contentId]
     * @Return java.util.List<com.xinqi.modules.discuss.notice.domain.CourseNoticeStudentLogEntity>
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/4/5 17:52
     */
    @Override
    public List<CourseNoticeStudentLogEntity> selectByContentId(Long contentId) {
        LambdaUpdateWrapper<CourseNoticeStudentLogEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(CourseNoticeStudentLogEntity::getContentId, contentId);
        return this.baseMapper.selectList(wrapper);
    }

    /**
     * 根据公告ID集合和学生ID获取列表
     *
     * @Title:
     * @MethodName: selectByNoticeIdAndStudentId
     * [contentIds, studentId]
     * @Return java.util.List<com.xinqi.modules.discuss.notice.domain.CourseNoticeStudentLogEntity>
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/4/5 17:58
     */
    @Override
    public List<CourseNoticeStudentLogEntity> selectByNoticeIdAndStudentId(List<Long> contentIds, Long studentId) {
        LambdaUpdateWrapper<CourseNoticeStudentLogEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CourseNoticeStudentLogEntity::getContentId, contentIds)
            .eq(CourseNoticeStudentLogEntity::getStudentId, studentId);
        return this.baseMapper.selectList(wrapper);
    }

    /**
     * 查询学生记录
     *
     * @Title:
     * @MethodName: selectPage
     * [pageable, query]
     * @Return com.xinqi.common.base.response.PageInfo<com.xinqi.modules.discuss.notice.dto.rsp.CourseNoticeStudentLogResultDTO>
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/22 14:24
     */
    @Override
    @DS("slaver")
    public PageInfo<CourseNoticeStudentLogResultDTO> selectPage(Param pageable, CourseNoticeStudentLogQueryDTO query) {
        return Pages.convert(this.baseMapper.selectPage1(Pages.page(pageable), query));
    }

    /**
     * 同步学生设置（学生日志记录不影响主业务，但存在数据量大的情况，故采用异步处理）
     *
     * @param entity
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void synchroStudent(CourseNoticeEntity entity) {
        if (Objects.isNull(entity)) {
            return;
        }
        // 查询班级内的所有主成员
        List<ClassStudentResultDTO> students = R.as(classStudentClient.findClassMasterStudentByClassId(entity.getClassId()));
        if (CollectionUtils.isEmpty(students)) {
            return;
        }
        //获取所有学生记录，防止重复
        List<CourseNoticeStudentLogEntity> logEntityList = this.selectByContentId(entity.getId());
        Map<Long, CourseNoticeStudentLogEntity> logEntityMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(logEntityList)) {
            logEntityList.forEach(logEntity -> {
                logEntityMap.put(logEntity.getStudentId(), logEntity);
            });
        }
        List<CourseNoticeStudentLogEntity> list = new ArrayList<>();
        students.forEach(student -> {
            //校验是存在于班级的学生(老师不算学生，公告的统计不计算老师)
            if (!logEntityMap.containsKey(student.getStudentId())) {
                //无数据
                CourseNoticeStudentLogEntity studentLogEntity = new CourseNoticeStudentLogEntity();
                studentLogEntity.setContentId(entity.getId());
                studentLogEntity.setStudentId(student.getStudentId());
                studentLogEntity.setClassId(entity.getClassId());
                studentLogEntity.setIsRead(YesNoNumberEnum.NO.getCode());
                studentLogEntity.setIsConfirm(YesNoNumberEnum.NO.getCode());
                list.add(studentLogEntity);
            }
        });
        //同步班级学生讨论内容(老师不算学生，公告的统计不计算老师)
        if (CollectionUtils.isNotEmpty(list)) {
            this.saveBatch(list);
        }
    }

    /**
     * 同步学生设置（学生日志记录不影响主业务，但存在数据量大的情况，故采用异步处理）
     *
     * @param noticeList
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void synchroStudent(List<CourseNoticeEntity> noticeList) {
        if (CollectionUtils.isEmpty(noticeList)) {
            return;
        }
        //返回结果
        List<CourseNoticeStudentLogEntity> studentLogList = new ArrayList<>();
        noticeList.forEach(notice -> {
            // 查询班级内的主成员信息
            List<ClassStudentResultDTO> students = R.as(classStudentClient.findClassMasterStudentByClassId(notice.getClassId()));
            if (CollectionUtils.isEmpty(students)) {
                return;
            }
            //获取所有学生记录，防止重复
            List<CourseNoticeStudentLogEntity> logEntityList = this.selectByContentId(notice.getId());
            Map<Long, CourseNoticeStudentLogEntity> logEntityMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(logEntityList)) {
                logEntityList.forEach(logEntity -> {
                    logEntityMap.put(logEntity.getStudentId(), logEntity);
                });
            }
            //同步班级成员讨论内容
            students.forEach(student -> {
                //校验是存在于班级的学生(老师不算学生，公告的统计不计算老师)
                if (!logEntityMap.containsKey(student.getStudentId())) {
                    //无数据
                    CourseNoticeStudentLogEntity studentLogEntity = new CourseNoticeStudentLogEntity();
                    studentLogEntity.setContentId(notice.getId());
                    studentLogEntity.setStudentId(student.getStudentId());
                    studentLogEntity.setClassId(notice.getClassId());
                    studentLogEntity.setIsRead(YesNoNumberEnum.NO.getCode());
                    studentLogEntity.setIsConfirm(YesNoNumberEnum.NO.getCode());
                    studentLogList.add(studentLogEntity);
                }
            });
        });
        if (CollectionUtils.isNotEmpty(studentLogList)) {
            this.saveBatch(studentLogList);
        }
    }

    /**
     * 新增学生同步（学生日志记录不影响主业务，但存在数据量大的情况，故采用异步处理）
     *
     * @param noticeList
     * @param classId
     * @param userId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void synchroStudent(List<CourseNoticeEntity> noticeList, Long classId, Long userId) {
        List<CourseNoticeStudentLogEntity> studentLogList = new ArrayList<>();
        if (CollectionUtils.isEmpty(noticeList)) {
            return;
        }
        List<Long> contentIds = noticeList.stream().map(CourseNoticeEntity::getId).collect(Collectors.toList());

        // 查询班级主学生信息列表
        ClassStudentResultDTO student = R.as(classStudentClient.findVirtualClassStudentByClassIdAndUserId(classId, userId));
        if (Objects.isNull(student)) {
            return;
        }
        //获取所有学生记录，防止重复
        List<CourseNoticeStudentLogEntity> logEntityList = this.selectByNoticeIdAndStudentId(contentIds, student.getStudentId());
        Map<Long, CourseNoticeStudentLogEntity> logEntityMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(logEntityList)) {
            logEntityList.forEach(logEntity -> {
                logEntityMap.put(logEntity.getContentId(), logEntity);
            });
        }
        noticeList.forEach(notice -> {
            if (!logEntityMap.containsKey(notice.getId())) {
                //无数据
                CourseNoticeStudentLogEntity studentLogEntity = new CourseNoticeStudentLogEntity();
                studentLogEntity.setContentId(notice.getId());
                studentLogEntity.setStudentId(student.getStudentId());
                studentLogEntity.setClassId(classId);
                studentLogEntity.setIsRead(YesNoNumberEnum.NO.getCode());
                studentLogEntity.setIsConfirm(YesNoNumberEnum.NO.getCode());
                studentLogList.add(studentLogEntity);
            }
        });
        if (CollectionUtils.isNotEmpty(studentLogList)) {
            this.saveBatch(studentLogList);
        }
    }

    /**
     * 已读
     *
     * @param result
     * @param userId
     */
    @Override
    public void synchroRead(CourseNoticeResultDTO result, Long userId) {

        //不存在 或 不是班级学生直接返回
        if (Objects.isNull(result) || !R.as(classStudentClient.checkIsStudent(result.getClassId(), userId))) {
            return;
        }

        // 查询身份关联主学生信息
        ClassStudentResultDTO mainStudent = R.as(classStudentClient.findVirtualClassStudentByClassIdAndUserId(result.getClassId(), userId));

        userId = Objects.nonNull(mainStudent) ? mainStudent.getStudentId() : userId;
        CourseNoticeStudentLogEntity studentLogEntity = this.selectByNoticeIdAndStudentId(result.getId(), mainStudent.getStudentId());
        //未结束都可新增
        if (Objects.isNull(studentLogEntity)) {
            if (!Objects.equals(DiscussReleaseStatusEnum.CLOSED.getCode(), result.getStatus())) {
                studentLogEntity = new CourseNoticeStudentLogEntity();
                studentLogEntity.setClassId(result.getClassId());
                studentLogEntity.setContentId(result.getId());
                studentLogEntity.setStudentId(mainStudent.getStudentId());
                //进行中 -- 已读，  未发布 -- 未读
                if (Objects.equals(DiscussReleaseStatusEnum.IN_PROGRESS.getCode(), result.getStatus())) {
                    studentLogEntity.setIsRead(YesNoNumberEnum.YES.getCode());
                } else {
                    studentLogEntity.setIsRead(YesNoNumberEnum.NO.getCode());
                }
                studentLogEntity.setIsConfirm(YesNoNumberEnum.NO.getCode());
                this.save(studentLogEntity);
            }
        } else {
            //已发布 -- 可完成已读
            if (Objects.equals(DiscussReleaseStatusEnum.IN_PROGRESS.getCode(), result.getStatus()) && Objects.equals(YesNoNumberEnum.NO.getCode(), studentLogEntity.getIsRead())) {
                studentLogEntity.setIsRead(YesNoNumberEnum.YES.getCode());

                this.updateById(studentLogEntity);
            }
        }
    }

}
